package com.hmall.order.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.common.client.ItemClient;
import com.hmall.common.client.UserClient;
import com.hmall.item.pojo.Item;
import com.hmall.order.dto.OrderDto;
import com.hmall.order.mapper.OrderMapper;
import com.hmall.order.pojo.Order;
import com.hmall.order.pojo.OrderDetail;
import com.hmall.order.pojo.OrderLogistics;
import com.hmall.order.service.IOrderDetailService;
import com.hmall.order.service.IOrderLogisticsService;
import com.hmall.order.service.IOrderService;
import com.hmall.user.pojo.Address;
import com.hmall.util.ThreadLocalUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.util.Date;

@Service
public class OrderService extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Autowired
    private ItemClient itemClient;

    @Autowired
    private UserClient userClient;

    @Autowired
    private IOrderDetailService orderDetailService;

    @Autowired
    private IOrderLogisticsService orderLogisticsService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 创建订单
     * @param orderDto
     * @return
     */
    @Override
    @Transactional
    public Long createOrder(OrderDto orderDto ) {
        //目标：封装Order、OrderDetail、OrderLogistics添加到对应的表中，扣库存。
        //1 根据itemId查询商品信息（远程调用）
        Item item = itemClient.selectById(orderDto.getItemId());
        //2 封装Order订单信息，添加到tb_order表中
        Order order=new Order();
        //2.1 计算总金额(商品单价*数量num)并封装
        long totalFee=item.getPrice()*orderDto.getNum();
        order.setTotalFee(totalFee);
        //2.2 封装其他订单数据
        order.setPaymentType(orderDto.getPaymentType());  //封装支付方式
        order.setUserId(ThreadLocalUtils.getUserId()); //封装用户id
        order.setStatus(1);  //状态为未支付
        Date now=new Date();   //系统当前时间
        order.setCreateTime(now);  //创建时间
        order.setUpdateTime(now);  //修改时间
        //2.3 添加订单信息到tb_order表中
        this.save(order);  //mybatisplus会将order的id封装到order对象中

        //3 封装OrderDetail订单详情信息，添加到tb_order_detail表中
        //3.1 封装数据
        OrderDetail orderDetail=new OrderDetail();
        orderDetail.setOrderId(order.getId());  //封装订单id
        orderDetail.setItemId(orderDto.getItemId());  //封装商品信息
        orderDetail.setNum(orderDto.getNum());  //封装购买的商品数量
        orderDetail.setName(item.getName());  //封装商品名称
        orderDetail.setPrice(item.getPrice());  //封装商品单价
        orderDetail.setSpec(item.getSpec());  //封装商品规格
        orderDetail.setImage(item.getImage());  //封装商品图片地址
        orderDetail.setCreateTime(now);  //创建时间
        orderDetail.setUpdateTime(now);  //修改时间
        //3.2 添加到tb_order_detail表中
        orderDetailService.save(orderDetail);

        //4 根据addressId查询地址信息（远程调用）
        Address address = userClient.findAddressById(orderDto.getAddressId());

        //5 封装OrderLogistics物流信息，添加到tb_order_logistics表中
        //5.1 封装数据
        OrderLogistics orderLogistics=new OrderLogistics();
        BeanUtils.copyProperties(address,orderLogistics);  //相同属性拷贝
        orderLogistics.setOrderId(order.getId());  //封装订单id
        orderLogistics.setCreateTime(now);  //创建时间
        orderLogistics.setUpdateTime(now);  //创建时间
        //5.2 添加到tb_order_detail表中
        orderLogisticsService.save(orderLogistics);

        //6 扣库存（远程调用）
        itemClient.updateStock(orderDto.getItemId(),-orderDto.getNum());

        //发送消息到延时队列中，30分中内进行付款。
        Message message= MessageBuilder.withBody((order.getId()+"").getBytes(StandardCharsets.UTF_8))
                        .setHeader("x-delay",30000)  //这里用30s模拟
                        .build();
        rabbitTemplate.convertAndSend("hmMall-order.pay-exchange","order.pay",message);

        return order.getId();
    }
}
